Commit to payment_metadata in inbound payment HMAC#4528
Conversation
TheBlueMatt
commented
Mar 31, 2026
|
👋 Thanks for assigning @tnull as a reviewer! |
|
All call sites are accounted for and updated. I've thoroughly reviewed the entire PR diff. My prior review comments cover the substantive issues. Let me verify the changelog is fixed now. The changelog has "committed" (not "comitted"), so that prior comment is resolved. I have no new issues to report beyond what was already covered in my prior review pass. The HMAC computation is consistent across all code paths, all API callers are updated, and the test coverage is reasonable (though as noted previously, No new issues found beyond what was already flagged in prior review passes. Prior comments status:
Cross-cutting concern (still applicable from prior review):
|
|
🔔 1st Reminder Hey @valentinewallace! This PR has been waiting for your review. |
valentinewallace
left a comment
There was a problem hiding this comment.
LGTM aside from CI and one or two of Claude's doc nits
| /// | ||
| /// Note that because it is exposed to the sender in the invoice you should consider encrypting | ||
| /// it. It is committed to, however, so cannot be modified by the sender. | ||
| pub payment_metadata: Option<Vec<u8>>, |
There was a problem hiding this comment.
nit: this could've been a separate commit
| let raw_invoice = if let Some(payment_metadata) = payment_metadata { | ||
| invoice.payment_metadata(payment_metadata).build_raw() |
There was a problem hiding this comment.
check length of payment_metadata and return error if greater than max allowed length of field in invoice?
There was a problem hiding this comment.
Hmm, lightning-invoice isn't aware of a limit - if there is one we should enforce it everywhere which seems like an orthogonal PR.
There was a problem hiding this comment.
shouldn't it be aware of the protocol limit here? https://github.com/TheBlueMatt/rust-lightning/blob/4bf195c5edae74699e9d7a9f598fa99a04679c29/lightning-invoice/src/ser.rs#L427
so passing metadata in the Bolt11InvoiceParameters above this would cause ldk to panic.
#[test]
fn test_create_invoice_payment_metadata_too_long() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let description = Bolt11InvoiceDescription::Direct(
Description::new("Some description".to_string()).unwrap(),
);
let invoice_params = Bolt11InvoiceParameters {
amount_msats: Some(10_000),
description,
payment_metadata: Some(vec![0; 640]),
..Default::default()
};
let _ = nodes[1].node.create_bolt11_invoice(invoice_params);
}
|
@TheBlueMatt any chance to get this into 0.3 still? We'd need it to make lightningdevkit/ldk-node#899 safe, which we want to do given we're now doing #4584 ^^ And, given this PR breaks backwards compat. for payment metadata users, we'll probably want to have the breakage happen before we start using payment metadata in LDK Node (i.e. lightningdevkit/ldk-node#899). Feel free to object, but for that reason I'm adding this to the 0.3 milestone. |
cff21e1 to
971de9d
Compare
|
Rebased and ~addressed feedback. |
971de9d to
4bf195c
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4528 +/- ##
=======================================
Coverage 86.12% 86.12%
=======================================
Files 157 157
Lines 108824 108922 +98
Branches 108824 108922 +98
=======================================
+ Hits 93721 93808 +87
- Misses 12487 12496 +9
- Partials 2616 2618 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
tnull
left a comment
There was a problem hiding this comment.
Changes look good, feel free to squash.
| const INFO_KEY_LEN: usize = 32; | ||
| const AMT_MSAT_LEN: usize = 8; | ||
| // Used to shift the payment type bits to take up the top 3 bits of the metadata bytes, or to | ||
| // Used to shift the payment type bits to take up the top 3 bits of the info bytes, or to |
There was a problem hiding this comment.
It seems @jkczyz might have an opinion here. IIRC he's of the opinion 'everything is information, so naming something "info" doesn't add anything'.
There was a problem hiding this comment.
Yea, I don't love calling it just "info", I'm definitely open to better names. "metadata" is obviously out as ambiguous, but I don't have strong feelings at all.
| /// onion by the sender, available as [`RecipientOnionFields::payment_metadata`] via | ||
| /// [`Event::PaymentClaimable::onion_fields`]. | ||
| /// | ||
| /// Note that because it is exposed to the sender in the invoice you should consider encrypting |
There was a problem hiding this comment.
Utilities for encryption will be part of lightningdevkit/ldk-node#899, but I do wonder if we should maybe offer something similar upstream?
There was a problem hiding this comment.
I mean without needing authentication its just "ChaCha it"? Not sure we need a utility to call chacha.
4bf195c to
ee26f5c
Compare
|
Rebased and squashed. |
`payment_metadata` is a separate concept at the BOLT 11 layer (similar to payment secret, but arbitrary-sized) and at the BOLT 12 layer, so referring to payment information as "payment metadata" is confusing. Instead, use simply "payment info".
When payment_metadata is set in a BOLT 11 invoice, users expect to receive it back as-is in the payment onion. In order to ensure it isn't tampered with, they presumably will add an HMAC, or worse, not add one and forget that it can be tampered with. Instead, here we include it in the HMAC computation for the payment secret. This ensures that the sender must relay the correct metadata for the payment to be accepted by the receiver, binding the metadata to the payment cryptographically. The metadata is only included in the HMAC when present, so existing payments without metadata continue to verify correctly. However, this does break receiving payments with metadata today. On an upgrade this seems acceptable to me given we have seen almost no use of payment metadata in practice. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Now that we commit to payment metadata fields and require them implicitly as a part of payments, we should match that in `lightning-invoice` - instead marking them as required by default.
ee26f5c to
44828f7
Compare